package cn.demo.weixin.mp.service;

import cn.demo.common.core.domain.R;
import cn.demo.common.core.domain.model.LoginUser;
import cn.demo.common.core.redis.RedisCache;
import cn.demo.common.exception.ServiceException;
import cn.demo.common.utils.StringUtils;
import cn.demo.um.domain.UmClientUser;
import cn.demo.um.mapper.UmClientUserMapper;
import cn.demo.weixin.mp.constant.WxMpConstants;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.service.WxOAuth2Service;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.stereotype.Service;

import java.util.UUID;

import static cn.demo.um.domain.table.UmClientUserTableDef.UM_CLIENT_USER;

@Service
@Slf4j
public class WxMpLoginService {
    @Resource
    private UmClientUserMapper clientUserMapper;
    @Resource
    private RedisCache redisCache;
    @Resource
    private WxMpService wxMpService;
    @Resource
    private WxOAuth2Service wxOAuth2Service;
    @Resource(name = "wxOpenService")
    private WxMpService wxOpenService;
    @Resource(name = "wxOpenOAuth2Service")
    private WxOAuth2Service wxOpenOAuth2Service;

    /**
     * 公众号登录
     *
     * @return
     */
    public LoginUser wxmplogin(String code) {
        return wxmpLogin(code, wxOAuth2Service, "lock:wxmpLogin:", WxMpConstants.LOGIN_PLATFORM_MPH5);
    }
    /**
     * 开放平台登录
     *
     * @return
     */
    public LoginUser wxOpenlogin(String code) {
        return wxmpLogin(code, wxOpenOAuth2Service, "lock:wxopenLogin:", WxMpConstants.LOGIN_PLATFORM_OPEN_PC);
    }

    private LoginUser wxmpLogin(String code, WxOAuth2Service wxOAuth2Service, String s, Integer platform) {
        if (StringUtils.isEmpty(code)) {
            throw new ServiceException("登录失败，code为空！");
        }
        if (code.startsWith("test_")) {
            return testLogin(code.replace("test_", ""));
        }
        WxOAuth2AccessToken accessToken = null;
        try {
            accessToken = wxOAuth2Service.getAccessToken(code);
        } catch (WxErrorException e) {
            log.error("微信授权登录失败！{}", e.getMessage());
        }
        if (null == accessToken) {
            throw new ServiceException("微信授权登录失败！");
        }
        String openId = accessToken.getOpenId();
        String unionId = accessToken.getUnionId();
        String uuid = UUID.randomUUID().toString();
        String lock = s + openId;
        try {
            if (redisCache.lockWait(lock, uuid)) {
                UmClientUser user = null;
                if (WxMpConstants.LOGIN_PLATFORM_MPH5.equals(platform)) {
                    user = clientUserMapper.selectOneByQuery(QueryWrapper.create().and(UM_CLIENT_USER.WXMP_OPENID.eq(openId).or(UM_CLIENT_USER.WX_UNIONID.eq(unionId))));
                } else {
                    user = clientUserMapper.selectOneByQuery(QueryWrapper.create().and(UM_CLIENT_USER.WXOPEN_OPENID.eq(openId).or(UM_CLIENT_USER.WX_UNIONID.eq(unionId))));
                }
                WxOAuth2UserInfo wxUserInfo = new WxOAuth2UserInfo();
                try {
                    wxUserInfo = wxOAuth2Service.getUserInfo(accessToken, "zh_CN");
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (null == user) {
                    user = new UmClientUser();
                    if (WxMpConstants.LOGIN_PLATFORM_MPH5.equals(platform)) {
                        user.setWxmpOpenid(openId);
                    } else {
                        user.setWxopenOpenid(openId);
                    }
                    user.setWxUnionid(unionId);
                    user.setAvatar(wxUserInfo.getHeadImgUrl());
                    user.setNickname(wxUserInfo.getNickname());
                    user.setSex(wxUserInfo.getSex());
                    clientUserMapper.insert(user);
                } else {
                    if (WxMpConstants.LOGIN_PLATFORM_MPH5.equals(platform)) {
                        user.setWxmpOpenid(openId);
                    } else {
                        user.setWxopenOpenid(openId);
                    }
                    if (StringUtils.isNotEmpty(wxUserInfo.getHeadImgUrl())) user.setAvatar(wxUserInfo.getHeadImgUrl());
                    if (StringUtils.isNotEmpty(wxUserInfo.getNickname())) user.setNickname(wxUserInfo.getNickname());
                    if (null != wxUserInfo.getSex()) user.setSex(wxUserInfo.getSex());
                    clientUserMapper.update(user);
                }

                LoginUser loginUser = new LoginUser();
                loginUser.setUserId(user.getId());
                return loginUser;
            } else {
                throw new ServiceException("登录失败！");
            }

        } finally {
            redisCache.releaseLock(lock, uuid);
        }

    }

    private LoginUser testLogin(String testUid) {
        UmClientUser user = clientUserMapper.selectOneById(testUid);

        if (null == user) {
            throw new ServiceException("登录失败！");
        }

        LoginUser loginUser = new LoginUser();
        loginUser.setUserId(user.getId());
        return loginUser;
    }

    public R<WxJsapiSignature> getWxSignature(String url) {
        try {
            WxJsapiSignature jsapiSignature = wxMpService.createJsapiSignature(url);
            return R.ok(jsapiSignature);
        } catch (WxErrorException e) {
            log.error("获取微信公众号H5签名失败！{}", e.getMessage());
            return R.fail("获取微信公众号H5签名失败");
        }
    }
}
